import random
import matplotlib.pyplot as plt
import numpy as np
# from scipy.interpolate import make_interp_spline


# 抽奖函数
# @param: luck_dict <dict>: {[要抽的值]: [该值的权重 (相对值 影响抽中该值的概率)]}
# return: [要抽的值]: 抽中的值 类型同参数中dict的key相同
def luck_draw(luck_dict: dict):
    k_list = []
    v_list = []
    for _k, _v in luck_dict.items():
        k_list.append(_k)
        v_list.append(_v)
    t = random.randint(0, sum(v_list))
    for i in range(len(v_list)):
        t -= v_list[i]
        if t <= 0:
            return k_list[i]


# 数据处理 打包 便于绘图
# @param: chain_dict <dict>: 全局变量
def get_cnrp_value_package(chain_dict: dict):
    # return:
    # data_package <dict>: {
    #     height <int>: cnrp.value <dict>,
    #     ...
    # }
    package = {}

    for h, block in chain_dict.items():
        package[h] = block.block_header.cnrp.value

    return package


# 接上一函数
# @param: get_cnrp_value_package return <dict>
def unpack_cnrp_value(package: dict):
    # return:
    # res_package <dict>: {
    #     'height' <list>: [block height <int>, ...],
    #     'value' <dict>: {
    #         node 1 <int>: node 1 rp by height <list>,
    #         ...
    #     }
    # }
    res_package = {'height': [], 'value': {}}

    for height, cnrp in package.items():
        for node, value in cnrp.items():
            rp_list = res_package['value'].get(node, [])
            rp_list.append(value)
            res_package['value'][node] = rp_list

        res_package['height'].append(height)

    del res_package['height'][0]

    height = res_package['height'][-1]

    # 补足 0
    for node, rp_list in res_package['value'].items():
        if len(rp_list) < height:
            for _ in range(height - len(rp_list) + 1):
                res_package['value'][node].insert(0, 0)

    return res_package


# =====================================================================


# 绘图 柱状图 最后block中的cnrp
# @param: chain <dict>: block chain
# return: none
def plot_bar(cnrp: dict):

    data_x = []
    data_y = []

    # for k, v in cnrp.items():
    #     data_x.append(str(k))
    #     data_y.append(v)

    for k in sorted(cnrp):
        data_x.append(str(k))
        data_y.append(cnrp[k])

    plt.axhline(y=0.5, c="red", ls='--', lw=1)
    plt.bar(range(len(data_y)), data_y, label='Node Rp', tick_label=data_x)
    plt.yticks(np.arange(0, 1.05, 0.05))

    # 添加数据标签 柱状图顶部标签
    for a, b in cnrp.items():
        plt.text(a - 1, b + 0.01, '%.02f' % b, ha='center', va='bottom', fontsize=6)

    # 添加图例
    plt.legend(fontsize=9)

    plt.tick_params(axis='both', labelsize=7)
    plt.show()


# 绘图 绘制折线图 绘制某一节点的RP变化记录
# @param: chain <dict>: block chain
#         target_node <int>: 目标节点
# return: none
def plot_line(chain: dict, target_node: int):
    # 以时间(块高度)为尺度观察的目标节点

    # node_dict[target_node].active_ratio = 10

    data_x = []
    data_y = [-1]

    # 绘图
    for h, b in chain.items():
        cnrp_value = b.block_header.cnrp.get('cnrp_value', {})
        y = cnrp_value.get(target_node, -1)
        if y != data_y[-1]:
            data_x.append(str(h))
            data_y.append(y)

    data_y = data_y[1:]

    data_length = len(data_y)
    x = range(data_length)

    # 数据平滑
    # x_new = np.linspace(0, data_length, 600)
    # power_smooth = make_interp_spline(x, data_y)(x_new)

    plt.plot(x, data_y)
    # plt.plot(x_new, power_smooth)
    plt.show()


# 打印目标节点的活动日志
# @param: chain <dict>: block chain
#         target_node <int>: 目标节点
# return: none
def print_node_log(chain: dict, target_node: int):
    print(' '*15 + '| Node' + str(target_node) + ' Act Log |' + ' '*10)

    table_header = '|   No | Height | TX Type | Source Node | Prev Height | Data Evaluate |       RP |'

    table_item_len = [len(table_header)]
    table_item_split = '-' * table_item_len[0]
    for w in [len(s) for s in table_header.split('|')]:
        if w > 0:
            table_item_len.append(w)

    print(table_item_split)
    print(table_header)

    prev_target_rp = -1
    # target_dict_start = False
    no = 1
    for h, b in chain.items():
        cnrp_value = b.block_header.cnrp.get('cnrp_value', {})
        y = cnrp_value.get(target_node, -1)
        if y != prev_target_rp:
            print(table_item_split)
            print('|%*s |%*s |%*s |%*s |%*s |%*s |%*s |' %
                  (table_item_len[1]-1, str(no),
                   table_item_len[2]-1, str(h),
                   table_item_len[3]-1, b.transactions.tx_type,
                   table_item_len[4]-1, b.transactions.tx_content.public_key_hash,
                   table_item_len[5]-1, b.transactions.previous_tx_id,
                   table_item_len[6]-1, b.transactions.tx_content.data_evaluate,
                   table_item_len[7]-1, str(y)
                   ))

            prev_target_rp = y
            no += 1


# 绘制第一张图
# @param: unpack_cnrp_value return <dict>
def plot_line_2(package: dict, node_select: list, label: list):
    plt.rcParams['figure.dpi'] = 400

    x = package['height']

    y_list = []
    i = 0
    for node in node_select:
        y = package['value'][node]
        y_list.append(y)

        plt.plot(x, y, label=label[i])

        # 数据平滑
        # x_smooth = np.linspace(0, x[-1], 600)
        # y_smooth = make_interp_spline(x, y)(x_smooth)
        # plt.plot(x_smooth, y_smooth, label='node-' + str(node))

        i += 1

    plt.axhline(y=0.5, c='grey', ls='--', lw=1)
    plt.yticks(np.arange(0, 1.1, 0.1))

    plt.xlabel('Height')
    plt.ylabel('Global Trust')
    # plt.title('Line Chart of Reputation Change')
    plt.legend(loc="upper left")

    # plt.gcf 函数取得当前绘制的 figure 并调用 savefig 函数
    foo_fig = plt.gcf()
    foo_fig.savefig('figures/figure-2.4.eps', format='eps', dpi=1000)

    # plt.savefig('figure-1.17.svg', format='svg')
    plt.show()


# 绘图 Figure-2 不同恶意节点比例下全局授权成功率
def plot_figure_2():
    pass

